package com.caijb.juc;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author caijb
 * @version 1.0
 * @data 2025/10/31 15:44
 */
public class ConditionDemo {

    public static void main(String[] args) {
        ProducerConsumerQueue queue = new ProducerConsumerQueue();
        for (int i = 0; i < 100; i++) {
            int finalI = i;
            new Thread(() -> {
                try {
                    // 往队列添加元素
                    queue.put(finalI);
                    System.out.println("Produced: " + finalI);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, "Producer-" + i).start();
        }

        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                try {
                    // 从队列获取元素
                    Integer item = queue.take();
                    System.out.println("Consumed: " + item);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }, "Consumer-" + i).start();
        }
    }

    public static class ProducerConsumerQueue {
        private final ReentrantLock lock = new ReentrantLock();
        private final Condition notEmpty = lock.newCondition();
        private final Condition notFull = lock.newCondition();
        private final Queue<Integer> queue = new LinkedList<>();
        private final int capacity = 5;

        public void put(Integer item) throws InterruptedException {
            lock.lock();
            try {
                // 到达容量限制时，添加需要等待
                while (queue.size() == capacity) {
                    System.out.println("队列已满，等待...，当前线程" + Thread.currentThread().getName());
                    // 添加队列等待
                    notFull.await();
                }
                // 添加元素
                queue.offer(item);
                System.out.println("当前线程：" +Thread.currentThread().getName()+ ",添加元素：" + item);
                // 通知消费者
                notEmpty.signal();
            } finally {
                lock.unlock();
            }
        }

        public Integer take() throws InterruptedException {
            lock.lock();
            try {
                // 队列为空时，消费需要等待
                while (queue.isEmpty()) {
                    notEmpty.await();
                }
                Integer item = queue.poll();
                notFull.signal();
                return item;
            } finally {
                lock.unlock();
            }
        }
    }

}
